package team.seekers.hula.teamwork.team.team.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import team.seekers.hula.common.entity.PageResult;
import team.seekers.hula.common.entity.result.ApiExceptionEnum;
import team.seekers.hula.common.entity.result.ApiException;
import team.seekers.hula.auth.service.MindUtils;
import team.seekers.hula.teamwork.team.team.entity.dao.TeamDO;
import team.seekers.hula.teamwork.team.team.entity.dto.ClassTeamInfoDTO;
import team.seekers.hula.teamwork.team.team.entity.dto.TeamAddPA;
import team.seekers.hula.teamwork.team.team.entity.dto.TeamQuery;
import team.seekers.hula.teamwork.team.team.entity.dto.TeamUpdatePA;
import team.seekers.hula.teamwork.team.team.entity.vo.TeamInfoVO;
import team.seekers.hula.teamwork.team.team.entity.vo.TeamListVO;
import team.seekers.hula.teamwork.team.team.mapper.TeamMapper;
import team.seekers.hula.teamwork.team.teamUser.entity.dao.TeamUserDO;
import team.seekers.hula.teamwork.team.teamUser.mapper.TeamUserMapper;
import team.seekers.hula.teamwork.team.teamUser.service.TeamUserService;
import team.seekers.hula.teamwork.teamTodo.entity.dao.TeamTodoDO;
import team.seekers.hula.teamwork.teamTodo.entity.vo.TeamTodoListVO;
import team.seekers.hula.teamwork.teamTodo.service.TeamTodoService;
import team.seekers.hula.teamwork.todo.entity.dao.TodoDO;
import team.seekers.hula.teamwork.todo.service.TodoService;

import java.util.ArrayList;
import java.util.List;

/**
 * 一个团队(或者说一个课程班) 服务实现类
 *
 * @author yiming
 */
@Service
public class TeamService extends ServiceImpl<TeamMapper, TeamDO>{

    @Autowired
    private TeamUserMapper teamUserMapper;

    @Autowired
    @Lazy
    private TeamTodoService teamTodoService;

    @Autowired
    private TeamUserService teamUserService;

    @Autowired
    @Lazy
    private TodoService todoService;

    /**
     * 根据id获取团队信息
     */
    public TeamInfoVO get(String id) {
        TeamDO teamDO = getById(id);
        if(teamDO == null){
            throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "团队已经解散");
        }

        TeamInfoVO teamInfoVO = new TeamInfoVO();
        // 基本信息赋值
        BeanUtils.copyProperties(teamDO, teamInfoVO);

        // 团队总发布待办数
        QueryWrapper<TeamTodoDO> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("team_id",id);
        List<TeamTodoDO> teamTodoDOS = teamTodoService.list(wrapper1);
        teamInfoVO.setTodoNum(teamTodoDOS.size());

        // 团队成员数
        QueryWrapper<TeamUserDO> wrapper2 = new QueryWrapper<>();
        wrapper2.eq("team_id",id);
        int memberNum = teamUserService.list(wrapper2).size();
        teamInfoVO.setMemberNum(memberNum);

        // 总完成率：团队待办的个人完成总数 / 团队待办数*团队成员数
        if (teamTodoDOS.size() == 0) {
            teamInfoVO.setFinishRate(0.0);
        } else {
            int finishNum = teamTodoDOS.stream()
                    .map(TeamTodoDO::getFinishNumber)
                    .reduce(Integer::sum).get();
            teamInfoVO.setFinishRate(finishNum * 1.0/(memberNum* teamTodoDOS.size()));
        }

        String userId = MindUtils.getUserId();
        // 标记：是否是我创建的
        if (teamDO.getUserId().equals(userId)) {
            teamInfoVO.isMyCreate();
        }
        return teamInfoVO;
    }

    /**
     * 新建团队
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(TeamAddPA teamAddPA) {
        String userId = MindUtils.getUserId();
        TeamDO teamDO = new TeamDO();

        BeanUtils.copyProperties(teamAddPA, teamDO);
        teamDO.setUserId(userId)
                .setIsDelete(0)
                .setMemberCount(1)
                .setFinishCount(0);
        boolean save = save(teamDO);
        if(!save){
            throw new ApiException(ApiExceptionEnum.DB_FAIL, "团队新建失败");
        }

        TeamUserDO teamUserDO = new TeamUserDO();
        teamUserDO.setUserId(userId)
                .setTeamId(teamDO.getId())
                .setIsMonitor(1);
        // 将队长加入团队
        int insert = teamUserMapper.insert(teamUserDO);
        if(insert == 0){
            throw new ApiException(ApiExceptionEnum.DB_FAIL, "团队新建失败");
        }
    }

    /**
     * 编辑团队
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(TeamUpdatePA teamUpdatePA) {
        TeamDO teamDO = getById(teamUpdatePA.getId());
        if(teamDO == null){
            throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "团队已经解散");
        }
        BeanUtils.copyProperties(teamUpdatePA, teamDO);
        updateById(teamDO);
    }

    /**
     * 删除团队
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(String teamId) {
        // 根据团队id删除团队待办
        teamTodoService.removeByTeamId(teamId);
        // 根据团队id删除team_user中记录
        teamUserService.removeByTeamId(teamId);
        // 删除团队 team
        boolean b = removeById(teamId);
        if(!b){
            throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "团队已经解散");
        }
    }

    /**
     * 加入团队
     */

    @Transactional(rollbackFor = Exception.class)
    public void joinIn(String teamId) {
        TeamUserDO teamUserDO = new TeamUserDO();
        teamUserDO.setTeamId(teamId).setUserId(MindUtils.getUserId());
        teamUserMapper.insert(teamUserDO);

        TeamDO teamDO = getById(teamId);
        teamDO.setMemberCount(teamDO.getMemberCount() + 1);
        updateById(teamDO);

        // 创建加入团队之前团队生成的未完成的待办
        List<TeamTodoListVO> list = teamTodoService.listUnFinished(teamId);
        if(list.size() > 0){
            ArrayList<TodoDO> todoDOS = new ArrayList<>();
            for (TeamTodoListVO teamTodoListVO : list) {
                TodoDO todoDO = new TodoDO();
                todoDO.setTeamTodoId(teamTodoListVO.getId())
                        .setUserId(MindUtils.getUserId())
                        .setTitle(teamTodoListVO.getTitle())
                        .setGmtEnd(teamTodoListVO.getGmtEnd());
                todoDOS.add(todoDO);
            }
            todoService.saveBatch(todoDOS);
        }


    }

    /**
     * 退出团队
     */
    @Transactional(rollbackFor = Exception.class)
    public void out(String teamId) {
        TeamDO teamDO = getById(teamId);
        String userId = MindUtils.getUserId();


        if(teamDO.getUserId().equals(userId)){
            // 如果是队长则直接删除原团队
            delete(teamId);
        }else {
            teamUserService.lambdaUpdate()
                    .eq(TeamUserDO::getTeamId,teamId)
                    .eq(TeamUserDO::getUserId,userId).remove();

            teamDO.setMemberCount(teamDO.getMemberCount() - 1);
            updateById(teamDO);

            // 移除所有相关待办
            List<String> teamTodoIdList = teamTodoService.teamTodoIdList(teamId);
            if(teamTodoIdList.size() > 0)
                todoService.lambdaUpdate().in(TodoDO::getTeamTodoId,teamTodoIdList).eq(TodoDO::getUserId,userId).remove();
        }
    }

    /**
     * 根据团队名分页查询
     */
    public PageResult<TeamListVO> pageQuery(TeamQuery teamQuery) {
        Page<TeamDO> teamPage = new Page<>(teamQuery.getPageNow(), teamQuery.getPageSize());
        LambdaQueryChainWrapper<TeamDO> wrapper = lambdaQuery();
        if (!StringUtils.isBlank(teamQuery.getName())) {
            wrapper.eq(TeamDO::getName, teamQuery.getName());
        }
        page(teamPage, wrapper);
        if(teamPage.getTotal() == 0){
            return new PageResult<>();
        }
        // 将team集合内容拷贝至teamListVO集合
        List<TeamListVO> teamListVOS = new ArrayList<>();
        for (TeamDO teamDO : teamPage.getRecords()) {
            TeamListVO teamListVO = new TeamListVO();
            BeanUtils.copyProperties(teamDO, teamListVO);
            teamListVOS.add(teamListVO);
        }
        return new PageResult<>(teamPage.getTotal(),teamListVOS);
    }

    /**
     * 渲染所有创建的团队
     */
    public List<TeamListVO> listMeCreate() {
        List<TeamDO> teamDOS = lambdaQuery().eq(TeamDO::getUserId, MindUtils.getUserId()).list();
        // 将team集合内容拷贝至teamListVO集合
        List<TeamListVO> teamListVOS = new ArrayList<>();
        for (TeamDO teamDO : teamDOS) {
            TeamListVO teamListVO = new TeamListVO();
            BeanUtils.copyProperties(teamDO, teamListVO);
            teamListVOS.add(teamListVO);
        }
        return teamListVOS;
    }

    /**
     * 渲染所有加入的团队
     */
    public List<TeamListVO> listMeIn() {
        QueryWrapper<TeamUserDO> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", MindUtils.getUserId());
        List<TeamUserDO> teamUserDOS = teamUserMapper.selectList(wrapper);

        List<TeamListVO> teamListVOS = new ArrayList<>();
        for (TeamUserDO teamUserDO : teamUserDOS) {
            String teamId = teamUserDO.getTeamId();
            TeamDO teamDO = getById(teamId);
            TeamListVO teamListVO = new TeamListVO();
            BeanUtils.copyProperties(teamDO, teamListVO);

            teamListVOS.add(teamListVO);
        }
        return teamListVOS;
    }

    public boolean isExist(String inviteCode){
        return getById(inviteCode) != null;
    }

    @Transactional(rollbackFor = Exception.class)
    public void bindClass(String inviteCode) {
        // 如果已加入某个班级则需要先退出
        List<String> teamIds = teamUserService.getTeamIds(MindUtils.getUserId());
        if(teamIds.size() != 0){
            TeamDO teamDO = lambdaQuery().select(
                    TeamDO::getId,
                    TeamDO::getName,
                    TeamDO::getSpeciality
            ).in(TeamDO::getId, teamIds).eq(TeamDO::getType, 1).one();

            if(teamDO != null){
                this.out(teamDO.getId());
            }
        }

        this.joinIn(inviteCode);
        // 根据班级特性做附加处理

    }

    public ClassTeamInfoDTO getClassTeamInfo(String userId) {
        List<String> teamIds = teamUserService.getTeamIds(userId);

        if(teamIds.size() == 0){
            return null;
        }


        TeamDO teamDO = lambdaQuery().select(
                TeamDO::getId,
                TeamDO::getName,
                TeamDO::getSpeciality
        ).in(TeamDO::getId, teamIds).eq(TeamDO::getType, 1).one();

        if(teamDO == null){
            return null;
        }

        ClassTeamInfoDTO classTeamInfoDTO = new ClassTeamInfoDTO();
        BeanUtils.copyProperties(teamDO,classTeamInfoDTO);
        return classTeamInfoDTO;
    }
}
